const Router = require("@koa/router");
const router = new Router({ prefix: "/today" });

// 根据公历出生时间计算五行个数，返回示例： { '金': 0, '木': 4, '水': 1, '火': 2, '土': 1 }
router.get("/calculateWuxing", async (ctx) => {
  const { birthYear, birthMonth, birthDay, birthHour } = ctx.query;

  // 验证输入参数
  if (!birthYear || !birthMonth || !birthDay) {
    ctx.status = 400;
    ctx.body = { error: "缺少必要的出生信息参数" };
    return;
  }

  // 将输入转换为数字
  const year = parseInt(birthYear);
  const month = parseInt(birthMonth);
  const day = parseInt(birthDay);
  const hour = birthHour ? parseInt(birthHour) : null;

  // 计算天干地支
  const yearGanZhi = calculateYearGanZhi(year);
  const monthGanZhi = calculateMonthGanZhi(year, month);
  const dayGanZhi = calculateDayGanZhi(year, month, day);
  const hourGanZhi =
    hour !== null ? calculateHourGanZhi(dayGanZhi.gan, hour) : null;

  // 计算八字中的五行分布
  const wuxingCount = { 金: 0, 木: 0, 水: 0, 火: 0, 土: 0 };

  // 计算年柱五行
  addWuxingFromGanZhi(wuxingCount, yearGanZhi.gan, yearGanZhi.zhi);

  // 计算月柱五行
  addWuxingFromGanZhi(wuxingCount, monthGanZhi.gan, monthGanZhi.zhi);

  // 计算日柱五行
  addWuxingFromGanZhi(wuxingCount, dayGanZhi.gan, dayGanZhi.zhi);

  // 计算时柱五行（如果有提供时辰）
  if (hourGanZhi) {
    addWuxingFromGanZhi(wuxingCount, hourGanZhi.gan, hourGanZhi.zhi);
  }

  ctx.body = wuxingCount;
});

// 天干对应的五行
const ganWuxing = {
  甲: "木",
  乙: "木",
  丙: "火",
  丁: "火",
  戊: "土",
  己: "土",
  庚: "金",
  辛: "金",
  壬: "水",
  癸: "水",
};

// 地支对应的五行
const zhiWuxing = {
  子: "水",
  丑: "土",
  寅: "木",
  卯: "木",
  辰: "土",
  巳: "火",
  午: "火",
  未: "土",
  申: "金",
  酉: "金",
  戌: "土",
  亥: "水",
};

// 天干序列
const ganList = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];

// 地支序列
const zhiList = [
  "子",
  "丑",
  "寅",
  "卯",
  "辰",
  "巳",
  "午",
  "未",
  "申",
  "酉",
  "戌",
  "亥",
];

// 计算年柱天干地支
function calculateYearGanZhi(year) {
  // 1984年是甲子年
  const baseYear = 1984;
  const offset = (year - baseYear) % 60;
  const ganIndex = offset % 10;
  const zhiIndex = offset % 12;

  // 处理负数情况
  const adjustedGanIndex = ganIndex >= 0 ? ganIndex : ganIndex + 10;
  const adjustedZhiIndex = zhiIndex >= 0 ? zhiIndex : zhiIndex + 12;

  return {
    gan: ganList[adjustedGanIndex],
    zhi: zhiList[adjustedZhiIndex],
  };
}

// 计算月柱天干地支
function calculateMonthGanZhi(year, month) {
  // 获取年干
  const yearGan = calculateYearGanZhi(year).gan;
  // 确定月干的起始偏移
  let baseGan;
  if (["甲", "己"].includes(yearGan)) baseGan = 0; // 甲己之年丙作首
  else if (["乙", "庚"].includes(yearGan)) baseGan = 2; // 乙庚之年戊作首
  else if (["丙", "辛"].includes(yearGan)) baseGan = 4; // 丙辛之年庚作首
  else if (["丁", "壬"].includes(yearGan)) baseGan = 6; // 丁壬之年壬作首
  else baseGan = 8; // 戊癸之年甲作首

  // 计算月干和月支
  const ganIndex = (baseGan + (month - 1)) % 10;
  // 寅月为正月
  const zhiIndex = (month + 1) % 12;

  return {
    gan: ganList[ganIndex],
    zhi: zhiList[zhiIndex],
  };
}

// 计算日柱天干地支（使用基姆拉尔森计算公式）
function calculateDayGanZhi(year, month, day) {
  // 调整月份
  if (month === 1 || month === 2) {
    month += 12;
    year--;
  }

  // 基姆拉尔森公式计算星期
  const century = Math.floor(year / 100);
  const y = year % 100;
  const weekDay =
    (day +
      Math.floor((26 * (month + 1)) / 10) +
      y +
      Math.floor(y / 4) +
      Math.floor(century / 4) -
      2 * century) %
    7;

  // 计算距离基准日期的天数（以1900年1月31日甲辰日为基准）
  const baseDate = new Date(1900, 0, 31); // 1900年1月31日
  const targetDate = new Date(year, month - 1, day);
  const diffTime = targetDate.getTime() - baseDate.getTime();
  const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));

  // 计算干支索引
  const ganIndex = ((diffDays % 10) + 10) % 10; // 加10再取模，避免负数
  const zhiIndex = ((diffDays % 12) + 12) % 12; // 加12再取模，避免负数

  return {
    gan: ganList[ganIndex],
    zhi: zhiList[zhiIndex],
  };
}

// 计算时柱天干地支
function calculateHourGanZhi(dayGan, hour) {
  // 根据日干确定时干的起始偏移
  const dayGanIndex = ganList.indexOf(dayGan);
  const baseGan = (dayGanIndex % 5) * 2;

  // 将小时转换为时辰（子时为0点到1点，丑时为1点到3点，以此类推）
  let zhiIndex;
  if (hour >= 23 || hour < 1) zhiIndex = 0; // 子时 (23:00-01:00)
  else if (hour < 3) zhiIndex = 1; // 丑时 (01:00-03:00)
  else if (hour < 5) zhiIndex = 2; // 寅时 (03:00-05:00)
  else if (hour < 7) zhiIndex = 3; // 卯时 (05:00-07:00)
  else if (hour < 9) zhiIndex = 4; // 辰时 (07:00-09:00)
  else if (hour < 11) zhiIndex = 5; // 巳时 (09:00-11:00)
  else if (hour < 13) zhiIndex = 6; // 午时 (11:00-13:00)
  else if (hour < 15) zhiIndex = 7; // 未时 (13:00-15:00)
  else if (hour < 17) zhiIndex = 8; // 申时 (15:00-17:00)
  else if (hour < 19) zhiIndex = 9; // 酉时 (17:00-19:00)
  else if (hour < 21) zhiIndex = 10; // 戌时 (19:00-21:00)
  else zhiIndex = 11; // 亥时 (21:00-23:00)

  // 计算时干
  const ganIndex = (baseGan + zhiIndex) % 10;

  return {
    gan: ganList[ganIndex],
    zhi: zhiList[zhiIndex],
  };
}

// 根据天干地支增加五行计数
function addWuxingFromGanZhi(wuxingCount, gan, zhi) {
  const ganWuxingValue = ganWuxing[gan];
  const zhiWuxingValue = zhiWuxing[zhi];

  if (ganWuxingValue) {
    wuxingCount[ganWuxingValue]++;
  }

  if (zhiWuxingValue) {
    wuxingCount[zhiWuxingValue]++;
  }
}

// 获取今日日历信息和穿衣颜色推荐
router.get("/", async (ctx) => {
  try {
    const response = await fetch("https://www.d5168.com/wuhang/");
    const html = await response.text();

    // 提取今日大吉色
    const mostAuspiciousColorMatch = html.match(
      /<font color="#FF0000">今日大吉色<\/font>：(.*?)，/
    );
    const todayMostAuspiciousColor = mostAuspiciousColorMatch
      ? mostAuspiciousColorMatch[1]
      : "";

    // 提取今日次吉色
    const secondAuspiciousColorMatch = html.match(
      /<font color="#008000">今日次吉色<\/font>：(.*?)，/
    );
    const todaySecondAuspiciousColor = secondAuspiciousColorMatch
      ? secondAuspiciousColorMatch[1]
      : "";

    // 提取今日不宜色
    const inauspiciousColorMatch = html.match(/今日不宜色：(.*?)，/);
    const todayInauspiciousColor = inauspiciousColorMatch
      ? inauspiciousColorMatch[1]
      : "";

    // 提取公历/阳历
    const gregorianDateMatch = html.match(
      /<span>公历\/阳历：<\/span>(.*?)<\/p>/
    );
    const gregorianDate = gregorianDateMatch
      ? gregorianDateMatch[1].trim()
      : "";

    // 提取农历/阴历
    const lunarDateMatch = html.match(/<span>农历\/阴历：<\/span>(.*?)<\/p>/);
    const lunarDate = lunarDateMatch ? lunarDateMatch[1].trim() : "";

    // 提取岁次
    const yearCycleMatch = html.match(/<span>岁次：<\/span>(.*?)<\/p>/);
    const yearCycle = yearCycleMatch ? yearCycleMatch[1].trim() : "";

    // 提取宜忌信息
    const suitableMatch = html.match(
      /<span><font color="#FF0000"><b>宜<\/b><\/font>：<\/span>(.*?)<\/p>/
    );
    const suitable = suitableMatch ? suitableMatch[1].trim() : "";

    const avoidMatch = html.match(/<span><b>忌<\/b>：<\/span>(.*?)<\/p>/);
    const avoid = avoidMatch ? avoidMatch[1].trim() : "";
    // 提取未来30天的五行穿衣信息
    const next30DaysText = html.match(
      /未来30天的五行穿衣：([\s\S]*?)(?=<\/div>|$)/i
    );
    // 如果找到匹配，进一步处理提取日期和颜色信息
    let next30Days = [];
    if (next30DaysText && next30DaysText[1]) {
      // 清理HTML标签和多余空白
      const cleanText = next30DaysText[1].replace(/<\/?[^>]+(>|$)/g, "").trim();
      // 将文本按日期分割成数组
      const daysPattern =
        /(\d{4}年\d{1,2}月\d{1,2}日)：([^0-9]+)(?=\d{4}年|$)/g;
      let match;
      while ((match = daysPattern.exec(cleanText)) !== null) {
        if (match[1] && match[2]) {
          // 提取日期
          const date = match[1].trim();
          // 提取颜色并分割成数组
          const colorsText = match[2].trim();
          const colors = colorsText
            .split(/[、，,]/)
            .map((color) => color.trim())
            .filter((color) => color);
          next30Days.push({
            date,
            colors,
          });
        }
      }
    }

    // 构建响应数据
    ctx.body = {
      todayMostAuspiciousColor,
      todaySecondAuspiciousColor,
      todayInauspiciousColor,
      gregorianDate,
      lunarDate,
      yearCycle,
      suitable,
      avoid,
      next30Days,
    };
  } catch (error) {
    console.error("获取五行穿衣指南失败:", error);
    ctx.status = 500;
    ctx.body = {
      error: "获取数据失败",
      message: error.message,
    };
  }
});

module.exports = router;
